package com.chs.recoginition.core.utils;

import com.chs.recoginition.core.exception.ApplicationException;
import com.chs.recoginition.core.exception.constant.ExceptionConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;
import org.springframework.validation.SmartValidator;
import org.springframework.validation.beanvalidation.SpringValidatorAdapter;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.Set;

/**
 * hibernate-validator校验工具类
 */
@Slf4j
@Component("validatorHelper")
public class ValidatorHelper {

    @Resource
    private Validator validator;

    private SmartValidator validatorAdapter;

    /**
     * 校验参数，用于普通参数校验 [未测试！]
     */
    public void validateParams(Object... params) {
        Set<ConstraintViolation<Object>> constraintViolationSet = validator.validate(params);
        if (!constraintViolationSet.isEmpty()) {
            String msg = ValidatorUtils.getErrorMessage(constraintViolationSet);
            throw new ApplicationException(ExceptionConstant.ILLEGAL_PARAM, msg);
        }
    }

    /**
     * 校验对象
     */
    public <T> void validate(T object, Class<?>... groups) {
        Set<ConstraintViolation<T>> constraintViolationSet = validator.validate(object, groups);
        if (!constraintViolationSet.isEmpty()) {
            String msg = ValidatorUtils.getErrorMessage(constraintViolationSet);
            throw new ApplicationException(ExceptionConstant.ILLEGAL_PARAM, msg);
        }
    }

    /**
     * 校验对象
     * 使用与 Spring 集成的校验方式。
     *
     * @param object 待校验对象
     * @param groups 待校验的组
     */
    public <T> void validateBySpring(T object, Class<?>... groups) {
        DataBinder dataBinder = getBinder(object);
        dataBinder.validate((Object[]) groups);

        BindingResult bindingResult = dataBinder.getBindingResult();
        if (bindingResult.hasErrors()) {
            String msg = ValidatorUtils.getErrorMessage(bindingResult);
            throw new ApplicationException(ExceptionConstant.ILLEGAL_PARAM, msg);
        }
    }

    private <T> DataBinder getBinder(T object) {
        DataBinder dataBinder = new DataBinder(object, ClassUtils.getShortName(object.getClass()));
        dataBinder.setValidator(getValidatorAdapter(validator));
        return dataBinder;
    }

    private SmartValidator getValidatorAdapter(Validator validator) {
        if (validatorAdapter == null) {
            validatorAdapter = new SpringValidatorAdapter(validator);
        }
        return validatorAdapter;
    }

}